package edu.kit.aifb.lidasora.ppmModel;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * {@inheritDoc} This class is a node data element for concurrent PPM models.
 * They guarantee synchronised accesses to all variables.
 * 
 * 
 * @author Daniel
 * @version 1.0
 * @see AbstractNodeData, NodeData
 */
final class NodeData {

	/*
	 * the basic counting value for this Node
	 */
	private AtomicInteger count = new AtomicInteger(1);

	/*
	 * count how often this Node has been predicted successfully
	 */
	private AtomicInteger successfulCount = new AtomicInteger(0);

	/*
	 * count how often this Node has been predicted falsely
	 */
	private AtomicInteger unsuccessfulCount = new AtomicInteger(0);

	private final AtomicLong timeCreated = new AtomicLong(
			System.currentTimeMillis());

	private AtomicLong timeChanged = new AtomicLong(System.currentTimeMillis());

	/**
	 * increment the count
	 * 
	 * increment the count; this should happen after each time the node is seen
	 * in a chain of events of type T
	 */
	void incrementCount() {
		this.timeChanged = new AtomicLong(System.currentTimeMillis());
		count.incrementAndGet();
	}

	/**
	 * Returns how often this node was part of a chain of events of type T
	 * 
	 * Returns how often this node was part of a chain of events of type T
	 * 
	 * @return how often this node was part of a chain of events of type T
	 */
	public int getCount() {
		return count.get();
	}

	/**
	 * Increment the count of how often this node has been truly predicted
	 * 
	 * Increment the count of how often this node has been truly predicted
	 */
	void incrementTruePredicted() {
		this.timeChanged = new AtomicLong(System.currentTimeMillis());
		this.successfulCount.incrementAndGet();
	}

	/**
	 * Get the count of how often this node has been truly predicted
	 * 
	 * Get the count of how often this node has been truly predicted
	 * 
	 * @return how often this node has been truly predicted
	 */
	public int getTruePredicted() {
		return this.successfulCount.get();
	}

	/**
	 * Increment the count of how often this node has been falsely predicted
	 * 
	 * Increment the count of how often this node has been falsely predicted
	 */
	void incrementFalsePredicted() {
		this.timeChanged = new AtomicLong(System.currentTimeMillis());
		this.unsuccessfulCount.incrementAndGet();
	}

	/**
	 * Get the count of how often this node has been falsely predicted
	 * 
	 * Get the count of how often this node has been falsely predicted
	 * 
	 * @return how often this node has been falsely predicted
	 */
	public int getFalsePredicted() {
		return this.unsuccessfulCount.get();
	}

	/**
	 * Returns the last time this node was accessed
	 * 
	 * Returns the last time this node was accessed. This can either be via a
	 * prediction or because it has been seen in a chain of events. The value
	 * returned comes from System.currentTimeMillis()
	 * 
	 * @return the last time this node has been accessed
	 */
	long getLastAccessedTime() {
		return this.timeChanged.get();
	}

	/**
	 * Returns the time of creation
	 * 
	 * Returns the time of creation of this node. The long-value is a result of
	 * a System.currentTimeMillis()-call.
	 * 
	 * @return the time of creation
	 */
	long getTimeCreated() {
		return this.timeCreated.get();
	}

}
